package com.yzkj.siot.facade.impl;

import cn.hutool.core.lang.UUID;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.yzkj.siot.context.CurUserCtx;
import com.yzkj.siot.domain.TenantDevice;
import com.yzkj.siot.domain.TenantDeviceData;
import com.yzkj.siot.dto.DataExportDTO;
import com.yzkj.siot.dto.DeviceDataDTO;
import com.yzkj.siot.exp.BizExp;
import com.yzkj.siot.facade.DeviceDataFacade;
import com.yzkj.siot.facade.DeviceFacade;
import com.yzkj.siot.kafka.KafkaService;
import com.yzkj.siot.result.PageParams;
import com.yzkj.siot.result.PageResponse;
import com.yzkj.siot.service.TaskTreadService;
import com.yzkj.siot.service.TenantDeviceDataService;
import com.yzkj.siot.util.EmailHelper;
import com.yzkj.siot.util.RedisUtil;
import com.yzkj.siot.util.TencentCOSHelper;
import com.yzkj.siot.vo.DeviceDataSummaryVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.mail.MessagingException;

@Slf4j
@Service
public class DeviceDataFacadeImpl implements DeviceDataFacade {

	@Autowired
	DeviceFacade deviceFacade;

	@Autowired
	TenantDeviceDataService deviceDataService;

	@Autowired
	TaskTreadService taskTreadService;

	@Autowired
	RedisUtil redisUtil;

	@Autowired
	KafkaService kafkaService;

	@Value(value = "${kafka-topic.deviceData}")
	String deviceDataKafkaTopic;

	@Autowired
	TencentCOSHelper tencentCOSHelper;

	@Autowired
	EmailHelper emailHelper;

	@Autowired
	TemplateEngine templateEngine;

	@Value("${sys.template.dataExportEmail}")
	String dataExportEmailTemplateName;

	@Override
	public PageResponse<TenantDeviceData> page(PageParams<TenantDeviceData> pageParams) {
		return null;
	}

	@Override
	public TenantDeviceData queryOne(int id) {

		return null;
	}

	@Override
	public TenantDeviceData saveOrUpdate(TenantDeviceData entity) {

		return null;
	}

	@Override
	public TenantDeviceData remove(int id) {
		return null;
	}

	@Override
	public Boolean batchRemove(List<Integer> idList) {
		return null;
	}

	@Override
	public Boolean batchSave(List<TenantDeviceData> entities) {
		return false;
	}

	@Override
	public Boolean pushData(DeviceDataDTO dto) {
		dto.setTenantId(CurUserCtx.get().getTenantId());
		kafkaService.sendMsg(deviceDataKafkaTopic, JSONUtil.toJsonStr(dto));
		return true;
	}

	@Override
	public List<DeviceDataSummaryVO> querySummary(Integer timeGranularity, Integer productDataId, String startTime,
			String endTime) {

		return deviceDataService.querySummary(timeGranularity, productDataId, startTime, endTime);
	}

	@Override
	public List<TenantDeviceData> queryListRealTime(int deviceId, int productId) {

		List<TenantDeviceData> res = new ArrayList<>();

		if (deviceId != 0) {
			List<TenantDeviceData> deviceDataList = queryListDeviceDataFromCache(deviceId);
			if (CollectionUtils.isEmpty(deviceDataList)) {
				throw new BizExp("设备离线或异常！");
			}
			res.addAll(deviceDataList);
		}

		if (deviceId == 0 && productId != 0) {
			TenantDevice deviceParams = new TenantDevice();
			deviceParams.setProductId(productId);

			PageParams<TenantDevice> pageParams = new PageParams<>();
			pageParams.setEntity(deviceParams);

			List<TenantDevice> deviceList = deviceFacade.page(pageParams).getRecords();
			for (TenantDevice device : deviceList) {
				res.addAll(queryListDeviceDataFromCache(device.getId()));
			}

		}

		if (deviceId == 0 && productId == 0) {
			List<TenantDevice> deviceList = deviceFacade.page(new PageParams<>()).getRecords();
			for (TenantDevice device : deviceList) {
				res.addAll(queryListDeviceDataFromCache(device.getId()));
			}
		}

		return res;
	}

	private List<TenantDeviceData> queryListDeviceDataFromCache(int deviceId) {
//        Object o = redisUtil.get( deviceDataRedisKey + ":" + deviceId);
//        if (o != null) {
//            return JSONUtil.toList(o.toString(), TenantDeviceData.class);
//        }
//        return new ArrayList<>();
		return new ArrayList<>();
	}

	@Override
	public Boolean exportExcel(int tenantId, String sendTo, int productId, int productDataId, int deviceId) {

		
		String exportNo = UUID.fastUUID().toString();
		String fileName = "./export-" + exportNo + ".xlsx";
		List<String> filePaths = new ArrayList<>();
		filePaths.add(fileName);
		ExcelWriter excelWriter = EasyExcel.write(fileName, DataExportDTO.class).build();
		WriteSheet writeSheet = EasyExcel.writerSheet("sheet").build();

		int count = deviceDataService.countExportData(tenantId, productId, productDataId, deviceId);

		int pageSize = 10000;
		int queryCount = count / pageSize + 1;

		for (int i = 0; i < queryCount; i++) {
			PageParams<DataExportDTO> pageParam = new PageParams<DataExportDTO>(i + 1, pageSize);
			List<DataExportDTO> dataRes = deviceDataService.pageExportData(tenantId, productId, productDataId, deviceId, pageParam);
			log.info("数据分片导出 总数据量{} 每页{}条 当前第{}页", count, pageSize, i + 1);
			if (dataRes != null && !CollectionUtils.isEmpty(dataRes)) {
				excelWriter.write(dataRes, writeSheet);
				dataRes.clear();
			}
		}

		excelWriter.close();
		try {
			// 模板引擎指向welcome.html页面
			// 从cos中读取模板文件路径
			String emailTemplate = templateEngine.process(dataExportEmailTemplateName, new Context());

			emailHelper.sendMail("【siot】设备数据导出", emailTemplate, filePaths, true, sendTo);
		} catch (MessagingException e) {
			log.error("导出数据 发送邮件失败", e);
		} finally {
			File exportFile = new File(fileName);
			if (exportFile.exists()) {
				exportFile.delete();
			}
		}

		return true;
	}
}
